/*
 * @Author: wuqingchun
 * @Date: 2024-04-29 13:49:00
 * @Description: 模板元编程 - 模板元函数
 * @LastEditors: wuqingchun
 * @LastEditTime: 2024-05-07 14:26:53
 */
#ifndef __TMP_FUNCTION_H__
#define __TMP_FUNCTION_H__

namespace mymeta
{
    template <typename T>
    struct is_reference
    {
        static constexpr bool value = false;
    };

    template <typename T>
    struct is_reference<T&>
    {
        static constexpr bool value = true;
    };

    template <typename T>
    struct is_reference<T&&>
    {
        static constexpr bool value = true;
    };


    template <typename T>
    struct is_integral
    {
        static constexpr bool value = false;
    };

    // 模板特化(针对特定类型实例化)
    template <>
    struct is_integral<int>
    {
        static constexpr bool value = true;
    };

    template <>
    struct is_integral<unsigned int>
    {
        static constexpr bool value = true;
    };

    template <>
    struct is_integral<short>
    {
        static constexpr bool value = true;
    };
    
    // primary template
    template <int N>  // non-type parameter N
    struct binary 
    {
        // an template instantiation inside the template itself, which contructs a recursion
        static constexpr int value = binary<N / 10>::value << 1 | N % 10;
    };

    // full specialization when N == 0
    template <> 
    struct binary<0> 
    {
        static constexpr int value = 0;
    };


    // 主模板
    template <typename T>
    struct remove_reference
    {
        using type = T;
    };

    // 偏特化
    template <typename T>
    struct remove_reference<T&>
    {
        using type = T;
    };

    // 偏特化
    template <typename T>
    struct remove_reference<T&&>
    {
        using type = T;
    };

    template <typename T>
    struct type_identity
    {
        using type = T;
    };

    template <typename T>
    struct type_identity<T&>
    {
        using type = T&;
    };

    template <typename T>
    struct type_identity<T&&>
    {
        using type = T&&;
    };


    template <typename T, T v>
    struct integral_constant
    {
        static constexpr T value = v;
        using value_type = T;
        //using type = integral_constant<T, v>;
        using type = integral_constant;

        // 到 value_type 的隐式类型转换
        constexpr operator value_type() const noexcept { return value + 1; }
        // 函数调用运算符重载
        constexpr value_type operator()() const noexcept { return value + 2; }
    };

    // alias
    template <bool B> using bool_constant = integral_constant<bool, B>;
    using true_type  = bool_constant<true>;
    using false_type = bool_constant<false>;


    template <typename T>
    struct is_reference_v2
    {
        using type = false_type;
    };

    template <typename T>
    struct is_reference_v2<T&>
    {
        using type = true_type;
    };

    template <typename T>
    struct is_reference_v2<T&&>
    {
        using type = true_type;
    };
    
}


#endif //__TMP_FUNCTION_H__